/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.tabbedproperties.composites;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.jface.text.Assert;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertyConstants;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetWidgetFactory;
import org.eclipse.uml2.uml.CollaborationUse;
import org.eclipse.uml2.uml.Dependency;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Property;

import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.commands.AddUMLElementToDiagram;
import com.cea.papyrus.core.commands.MoveInListCommand;
import com.cea.papyrus.core.commands.factories.DiagramElementDeleteCommandFactory;
import com.cea.papyrus.core.commands.factories.UMLDi2ElementDeleteFactory;
import com.cea.papyrus.core.editor.CommandStackUtils;
import com.cea.papyrus.core.helper.GraphEdgeHelper;
import com.cea.papyrus.core.utils.LookForElement;
import com.cea.papyrus.diagram.classdiagram.helper.EdgeDependencyHelper;
import com.cea.papyrus.diagram.composite.command.DisplaybindingCommand;
import com.cea.papyrus.diagraminterchange2.di2.DiagramElement;
import com.cea.papyrus.diagraminterchange2.di2.GraphConnector;
import com.cea.papyrus.diagraminterchange2.di2.GraphEdge;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;
import com.cea.papyrus.ui.RoleCreationDialog;

/**
 * Displays the subjects of a use case in a composite.
 * 
 * @author
 * @since 20 nov. 06
 */
public class RoleComposite extends DecoratedTableComposite implements ISectionComposite {

	/**
	 * The Constructor.
	 */
	public RoleComposite() {
		super("Roles");
	}

	/**
	 * The Class ViewElementButtonListener.
	 */
	private class ViewElementButtonListener implements MouseListener {

		/**
		 * Mouse double click.
		 * 
		 * @param e the e
		 */
		public void mouseDoubleClick(MouseEvent e) {
			// do nothing
		}

		/**
		 * Mouse down.
		 * 
		 * @param e the e
		 */
		public void mouseDown(MouseEvent e) {
			// do nothing
		}

		/**
		 * Mouse up.
		 * 
		 * @param e the e
		 */
		public void mouseUp(MouseEvent e) {
			// if there is no graphics, it is not use to draw an link
			if( graphicalCollaborationUse!=null){ 
				//get seleted item
				TableItem[] tableItems = table.getSelection();
				for (int i=0; i< tableItems.length;i++){
					//getDependency from item
					Dependency dependency = (Dependency) tableItems[i].getData(KEY);
					displayRoleBinding(dependency);
				}
			}
		}
	}

	/**
	 * The Constant KEY.
	 */
	private final static String KEY = "role_data";
	
	/**
	 * The Constant IMG_DISPLAY.
	 */
	private static final Image IMG_DISPLAY	= PapyrusPlugin.getImage(PapyrusPlugin.PAPYRUS_ICONS_16x16+"ConsoleView_16x16.gif");

	/**
	 * Operation for which methods are displayed.
	 */
	private CollaborationUse collaborationUse;


	/**
	 * 
	 */
	protected Button viewElementButton;
	
	/**
	 * 
	 */
	private DiagramElement graphicalCollaborationUse;
	
	/**
	 * 
	 */
	protected MouseListener viewElementButtonListener;

	/**
	 * 
	 * 
	 * @param collaborationUse 
	 */
	public void setCollaborationUse(CollaborationUse collaborationUse){
		this.collaborationUse=collaborationUse;
	}

	/**
	 * Refresh.
	 */
	@Override
	public void refresh() {
		if( !table.isDisposed()&& (collaborationUse!=null)){
			// Remove subjects from table 
			table.removeAll();
			if(collaborationUse.getType()==null){
				addButton.setEnabled(false);

			}
			else{
				addButton.setEnabled(true);
			}
			// Read and add subjects
			Iterator<Dependency> it = collaborationUse.getRoleBindings().iterator();
			while (it.hasNext()) {
				Dependency dependency = it.next();
				TableItem item = new TableItem(table, SWT.BORDER);
				item.setImage(PapyrusPlugin.getImage(PapyrusPlugin.UML_ICONS_16x16+"Property.gif"));
				item.setData(KEY, dependency);
				item.setText(((NamedElement)dependency.getClients().get(0)).getName()+" --> "
						+((NamedElement)dependency.getSuppliers().get(0)).getName());
			}
		}
	}

	/**
	 * Adds the button pressed.
	 */
	@Override
	public void addButtonPressed() {
		RoleCreationDialog dialog= new RoleCreationDialog(composite.getShell(),"Properties: ", "Roles: ");
		dialog.setCollaborationUse(collaborationUse);
		dialog.create();
		dialog.open();
		Dependency dependency=(Dependency)dialog.getValue();
		displayRoleBinding(dependency);

	}

	
	/**
	 * this method is used to display the role binding in the view.
	 * 
	 * @param dependency thaht represent the uml Element
	 */
	public void displayRoleBinding(Dependency dependency){
		if (dependency!=null){
			Property rolePlayer = (Property)dependency.getClients().get(0);
			//1. test if the poperty graphElement that play the role exist
			ArrayList graphicalRolePlayers=LookForElement.lookForGraphElement(rolePlayer, graphicalCollaborationUse.getContainer(), new ArrayList());
			//get the graphical role player
			GraphElement graphicalRolePlayer=null;
			if (graphicalRolePlayers.size()>=1){
				graphicalRolePlayer=(GraphElement)graphicalRolePlayers.get(0);
			}
			//the graphical palyer don't exist so it is created
			if (graphicalRolePlayer==null){
				Command command=new AddUMLElementToDiagram(rolePlayer, graphicalCollaborationUse.getContainer(), null, null);
				CommandStackUtils.getCommandStack().execute(command);
				graphicalRolePlayers=LookForElement.lookForGraphElement(rolePlayer, graphicalCollaborationUse.getContainer(), new ArrayList());
				graphicalRolePlayer=(GraphElement)graphicalRolePlayers.get(0);
			}
			GraphEdgeHelper geh= new GraphEdgeHelper();
			DisplaybindingCommand command = new DisplaybindingCommand((GraphNode)graphicalRolePlayer,null, null);
			command.setCollaborationUse(collaborationUse);
			command.setTarget((GraphElement)graphicalCollaborationUse, new Point(
					((GraphNode)graphicalCollaborationUse).getPosition().x +((GraphNode)graphicalCollaborationUse).getSize().width/2,
					((GraphNode)graphicalCollaborationUse).getPosition().y+((GraphNode)graphicalCollaborationUse).getSize().height));
			command.setOwner(graphicalCollaborationUse.getContainer());
			CommandStackUtils.getCommandStack().execute(command);
			refresh();
			}
	}
	
	/**
	 * Down button pressed.
	 */
	@Override
	public void downButtonPressed() {
		CompoundCommand compoundCommand = new CompoundCommand();
		TableItem[] tableItems = table.getSelection();

		for(int i = (tableItems.length-1); i >= 0; i--) {
			// Get subjects list
			List subjects = collaborationUse.getRoleBindings();
			// Get subject
			Dependency dependency = (Dependency) tableItems[i].getData(KEY);
			int newIndex = table.indexOf(tableItems[i]) + 1;
			if(newIndex < subjects.size()) {
				// Move
				compoundCommand.add(new MoveInListCommand(subjects, dependency, newIndex));
			}
		}
		CommandStack stack = CommandStackUtils.getCommandStack();
		Assert.isNotNull(stack, "Impossible to adapt current editor into a CommandStack");
		stack.execute(compoundCommand);
	}

	/**
	 * Edits the item.
	 * 
	 * @param item the item
	 */
	@Override
	public void editItem(TableItem item) {
		if (item == null) {
			return;
		}
		// Get subject linked to the item
		Dependency subject = (Dependency)item.getData(KEY);

		// TODO edit a classifier
	}

	/**
	 * Removes the button pressed.
	 */
	@Override
	public void removeButtonPressed() {
		// Get selection and remove it
		TableItem[] tableItems = table.getSelection();
		for(int i = 0; i < tableItems.length ; i++) {
			// Get subject remove umlusecase from its usecase list 
			// And remove it from the subjects list
			Dependency dependency = (Dependency) tableItems[i].getData(KEY);
			CompoundCommand ccommand=new CompoundCommand();
//			deletion of the link
			if( graphicalCollaborationUse!=null){
//				look for the graphical Property
				Property roleplayer= (Property)dependency.getClients().get(0);
				ArrayList graphicalRoleplayers=LookForElement.lookForGraphElement(roleplayer, (GraphElement)graphicalCollaborationUse.getContainer(),new ArrayList() );
				if (graphicalRoleplayers.size()!=0){
					//the graphica poperty is foun so we look for edge that represent the role binding
					GraphNode graphicalRolePlayer=(GraphNode)graphicalRoleplayers.get(0);
					//look for anchors of the graphicalRolePlayer
					Iterator<GraphConnector> itConnector=graphicalRolePlayer.getAnchorage().iterator();
					while( itConnector.hasNext()){
						//we found a connecter
						GraphConnector currentConnector= itConnector.next();
						//we found an edge
						GraphEdge edge=(GraphEdge)currentConnector.getGraphEdge().get(0);
						if( edge.getSemanticModel()!=null &&
								((Uml1SemanticModelBridge)edge.getSemanticModel()).getElement()!=null&&
								(((Uml1SemanticModelBridge)edge.getSemanticModel()).getElement() instanceof CollaborationUse)){
							// we have found the edge that represents the role binding
							// a command is created to suppress this graphElement
							ccommand.add(DiagramElementDeleteCommandFactory.eINSTANCE.createCommand(edge));

						}
					}
				}

			}
			//deletion of the dependency
			EdgeDependencyHelper edh= new EdgeDependencyHelper();
			ccommand.add(UMLDi2ElementDeleteFactory.eINSTANCE.createCommand(dependency));

			//edh.deconnect((Element)dependency.getClients().get(0), (Element)dependency.getSuppliers().get(0), dependency);
			//collaborationUse.getRoleBindings().remove(dependency);
			//this command is executed in last if not the thread is stopped to refresh.
			CommandStackUtils.getCommandStack().execute(ccommand);

		}
	}

	/**
	 * Up button pressed.
	 */
	@Override
	public void upButtonPressed() {
		CompoundCommand compoundCommand = new CompoundCommand();
		TableItem[] tableItems = table.getSelection();
		// Get subject list
		List subjects = collaborationUse.getRoleBindings();
		// Get subject
		for(int i = 0; i < tableItems.length ; i++) {
			Dependency dependency = (Dependency) tableItems[i].getData(KEY);
			int newIndex = table.indexOf(tableItems[i]) - 1;
			if (newIndex >= 0) {
				compoundCommand.add(new MoveInListCommand(subjects, dependency, newIndex));
			}
		}
		CommandStack stack = CommandStackUtils.getCommandStack();
		Assert.isNotNull(stack, "Impossible to adapt current editor into a CommandStack");
		stack.execute(compoundCommand);
	}
	
	/**
	 * 
	 * 
	 * @param factory 
	 * @param parent 
	 * 
	 * @return 
	 */
	public Composite createContent(Composite parent,
			TabbedPropertySheetWidgetFactory factory) {
		composite= super.createContent(parent, factory);
//		Button ViewElement

		viewElementButton = factory.createButton(composite, "", SWT.PUSH);
		viewElementButton.setVisible(true);
		viewElementButton.setImage(IMG_DISPLAY);
		viewElementButton.setToolTipText("View Element");

		FormData data = new FormData();
		data.top  = new FormAttachment(0, 0);
		data.right = new FormAttachment(downButton, -ITabbedPropertyConstants.HSPACE);
		viewElementButton.setLayoutData(data);
		viewElementButton.addMouseListener(viewElementButtonListener = new ViewElementButtonListener());	

//		update label position
		label.setLayout(new FormLayout());
		data = new FormData();
		data.left = new FormAttachment(0, ITabbedPropertyConstants.HSPACE);
		data.right = new FormAttachment(viewElementButton, -ITabbedPropertyConstants.HSPACE);
		data.top  = new FormAttachment(0, 0);
		label.setLayoutData(data);

		return composite;
	}

	/**
	 * 
	 * 
	 * @param diagramElement 
	 */
	public void setGraphicalNode(DiagramElement diagramElement) {
		this.graphicalCollaborationUse =diagramElement;

	}

	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.core.ui.composites.DecoratedTableComposite#dispose()
	 */
	/**
	 * 
	 */
	public void dispose(){
		super.dispose();
		if(viewElementButton!=null && !viewElementButton.isDisposed())
			viewElementButton.removeMouseListener(viewElementButtonListener);
	}
}